/***************************************************************************
 *   Copyright (C) 2008 by Milambert									   *
 *   nexus6b@gmail.com   												   *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "config.h"
#include "common.h"
#include "confHandler.h"
#include "mysqlHandler.h"

int lockFd;

void writeLog(char *mess){
#ifdef DEBUG
	//we are in debug mode so print it on screen
	fprintf(stdout, "%s\n", mess);
#else
	FILE *logFile;
	logFile = fopen(LOG_FILE, "a"); 
	
	if (!logFile){
		perror("EE:    open log file failed");
		return;
	}
	fprintf(logFile, "\n%s", mess);
		fclose(logFile);
#endif
}

void initServer(void){
	char pid[32];
	//int fic;
	
	if(daemon(0, 0)){
		writeLog("EE:	echec daemon");
		exit(EXIT_FAILURE);
	}
	
	//changement du repertoire courrant
	if (chdir(RUN_DIR)){
		writeLog("EE:	echec chdir");
		exit(EXIT_FAILURE);
	}
	
	//changement des droits de création
	umask(0222);
	
	//lock file
	lockFd = open(LOCK_FILE, O_RDWR|O_CREAT, 0640);
	if (lockFd < 0){
		writeLog("EE:	echec open");
		exit(EXIT_FAILURE);
	}
	if (lockf(lockFd, F_TLOCK, 0) < 0){
		writeLog("EE:	echec lockf");
		exit(EXIT_FAILURE);
	}
	sprintf(pid, "%d\n", getpid());
	write(lockFd, pid, strlen(pid));
	
	//gestion des signeaux
	signal(SIGCHLD, SIG_IGN);		//ignore child
	signal(SIGTSTP, SIG_IGN);		//ignore tty signals
	signal(SIGTTOU, SIG_IGN);
	signal(SIGTTIN, SIG_IGN);
	signal(SIGHUP, signalHandler);	//SIGHUP
	signal(SIGTERM, signalHandler);	//SIGTERM
}

void signalHandler(int signal){
	switch(signal){
		case SIGHUP:
				break;
		case SIGTERM:
				writeLog("II:	termined by SIGTERM");
				flushMem();
				closeMysql();
				//remove lock file
				if (close(lockFd) < 0){
					writeLog("EE:	echec close");
				}
				if(remove(LOCK_FILE) < 0){
					writeLog("EE:	echec remove");
				}
				writeLog("FIN");
				exit(EXIT_SUCCESS);
				break;
	}
}

int initSocket(void){
	struct sockaddr_in serveurAddr;
	int sockfd, yes = 1;
	
	//using UPD DATAGRAMMES
	if((sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1){
			writeLog("EE:    echec socket");
			exit(EXIT_FAILURE);
		}
		
	//disable "address already in use" error message
	if(setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1){
		writeLog("EE:    echec set SO_REUSEADDR");
		exit(EXIT_FAILURE);
	}
	
	serveurAddr.sin_family = AF_INET;
	serveurAddr.sin_port = htons(sockPort);
	serveurAddr.sin_addr.s_addr = INADDR_ANY;
	memset(serveurAddr.sin_zero, '\0', sizeof(serveurAddr.sin_zero));
	
	//enable broadcasting
	//if(setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &yes, sizeof(int)) == -1){
	//	writeLog("EE:	echet set Broadcast");
	//	return 0;
	//}
	
	if(bind(sockfd, (struct sockaddr *)&serveurAddr, sizeof serveurAddr) == -1){
		writeLog("EE:	echec bind");
		exit(EXIT_FAILURE);
	}
	
	return sockfd;
}

void flushMem(void){
	if(myUser != NULL)
		free(myUser);
	if(myPwd != NULL)
		free(myPwd);
	if(myHost != NULL)
		free(myHost);
	if(myDB != NULL)
		free(myDB);
}
